package com.example.lklibrary.bi;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.example.lklibrary.bi.bean.CollectorObj;
import com.example.lklibrary.bi.bean.DeviceBean;
import com.example.lklibrary.bi.bean.ExceptionInfo;
import com.example.lklibrary.bi.cache.LKDbManager;
import com.example.lklibrary.bi.cache.models.LKSessionData;
import com.example.lklibrary.bi.config.LKConfig;
import com.example.lklibrary.bi.http.LkCollectorHttp;
import com.example.lklibrary.bi.session.SessionConfig;
import com.example.lklibrary.bi.utils.LKCollectJsonUtil;
import com.example.lklibrary.bi.utils.LKNetUtils;
import com.example.lklibrary.bi.utils.LKSPUtil;
import com.google.gson.Gson;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

import bolts.Task;

/**
 * 1、sessionId的生成规则：
 * sessionId的生成规则： md5（设备ID+用户Id+时间戳）
 * 2、sessionId的生命周期：
 * 进入生成新的sessionId
 * 进入后台sessionId生命周期结束
 * 杀进程sessionId生命周期结束
 * 3、上传规则：
 * 进入上传
 * 退出上传
 * 日志积累到400条上传
 * 程序切换到后台上传
 */
public class LKCollector {

    private static String mUid = "";
    private static Gson gson;

    /**
     * 初始化行为统计
     *
     * @param uid      用户ID
     * @param appKey   APP的appkey
     * @param userInfo 用户信息
     */
    public static void initLKCollector(final Context context, final String uid, String appKey, String userInfo) {
        mUid = uid;
        //初始化位置信息
        LkCollectorHttp.init().getArea();
        //存储常用信息
        LKSPUtil.getInstance().init(context);
        LKSPUtil.getInstance().putStringValue("appKey", appKey);
        LKSPUtil.getInstance().putStringValue("userInfo", userInfo);
        LKSPUtil.getInstance().putStringValue("mobileOperator", getOperator(context));
        LKSPUtil.getInstance().putStringValue("connection", getConnect(context));
        LKSPUtil.getInstance().putStringValue("appVersion", getVersionName(context));

    }

    /**
     * appLaunch
     *
     * @param context
     */
    protected static void appLaunch(final Context context) {
        LKCollector.saveSession(context, "appLaunch",
                "", null, null, null, null);

        if (LKNetUtils.isWifiEthernetConnect(context)) {
            checkUpload(context);
        }

        //查看是否有崩溃信息
        String errorInfo = LKSPUtil.getInstance().getStringValue("errorInfo", "");
        if (errorInfo.length() > 0) {
            LKSPUtil lp = LKSPUtil.getInstance();
            ExceptionInfo exceptionInfo = new ExceptionInfo();
            exceptionInfo.appId = lp.getStringValue("appKey", "");
            exceptionInfo.appVersion = lp.getStringValue("appVersion", "");
            exceptionInfo.deiceName = Build.MODEL;
            exceptionInfo.errorInfo = errorInfo;
            exceptionInfo.errorTime = lp.getStringValue("errorTime", "");
            exceptionInfo.sysVersion = lp.getStringValue("Android", "");
            Gson gson = new Gson();
            String exception = gson.toJson(exceptionInfo);
            LkCollectorHttp.init().upExceptionInfo(LKConfig.UP_EXCEPTION_INFO, exception);
        }
    }

    /**
     * appEnd
     *
     * @param context
     * @param duration 行为时长
     */
    protected static void appEnd(final Context context, String duration) {
        LKCollector.saveSession(context, "appEnd",
                duration, null, null, null, null);
    }

    /**
     * pageDuration
     *
     * @param context
     * @param duration 行为时长
     * @param pageName 页面信息
     */
    protected static void pageDuration(final Context context,
                                       String duration,
                                       String pageName) {
        LKCollector.saveSession(context, "pageDuration",
                duration, pageName, null, null, null);
    }

    /**
     * customEvent
     *
     * @param context
     * @param eventId    自定义ID
     * @param label      行为标签
     * @param map 行为属性
     */
    public static void customEvent(final Context context,
                                   String eventId,
                                   String label,
                                   Map<String, String> map) {
        if(null == gson){
            gson = new Gson();
        }
        String attributes = gson.toJson(map);
        LKCollector.saveSession(context, "customEvent",
                null, null, eventId, label, attributes);
    }


    /**
     * 保存一条session数据
     *
     * @param context
     * @param action     行为统计类型
     * @param duration   行为时长
     * @param pageName   页面信息
     * @param eventId    自定义ID
     * @param label      行为标签
     * @param attributes 行为属性
     */
    private static void saveSession(final Context context,
                                    String action,
                                    String duration,
                                    String pageName,
                                    String eventId,
                                    String label,
                                    String attributes) {
        if (context == null) {
            return;
        }
        // 更新session
        String sessionId = SessionConfig.updateSessionId(android.os.Build.SERIAL, mUid);
        String date = String.valueOf(System.currentTimeMillis());
        final LKSessionData LKData = new LKSessionData();
        LKData.timeId = System.currentTimeMillis();
        LKData.sessionId = sessionId;
        LKData.uid = mUid;
        LKData.action = action;
        LKData.date = date;
        LKData.duration = duration;
        LKData.pageName = pageName;
        LKData.eventId = eventId;
        LKData.label = label;
        LKData.attributes = attributes;

        Task.callInBackground(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                //设置线程优先级为后台
                android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
                // 插入数据
                LKDbManager.getInstance().insertLKSessionData(context, LKData);
                // 超过400条上传
                int count = LKDbManager.getInstance().getLKSessionDataCount(context);
                if (count >= LKConfig.UPLOAD_COUNT) {
                    upload_Sync(context);
                }

                if (count > LKConfig.SAVE_COUNT) {
                    LKDbManager.getInstance().batchDeleteLKSessionData(context);
                }

                return null;
            }
        });
    }

    /**
     * 检查是否上传
     * wifi 直接上传，不判断
     * 非wifi 判断一天
     *
     * @param context
     */
    private static void checkUpload(final Context context) {
        // wifi
        if (LKNetUtils.isWifiEthernetConnect(context)) {
            upload_Async(context);
        }
        // 非wifi
        else {
            // 获取上次的上传时间
            LKSPUtil.getInstance().init(context);
            Long preUploadTime = LKSPUtil.getInstance().getLongValue("uploadTime", 0);
            if (System.currentTimeMillis() - preUploadTime >= LKConfig.ONE_DAY_INMillS) {
                upload_Async(context);
            }
        }
    }

    /**
     * 上传日志(直接上传)
     *
     * @param context
     */
    private static void upload_Async(final Context context) {
        // 查询session数据、上传、删除
        Task.callInBackground(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                //设置线程优先级为后台
                android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
                upload_Sync(context);
                return null;
            }
        });

    }

    /**
     * 同步该上传方法，防止多线程出错
     */
    private static synchronized void upload_Sync(final Context context) {

        // 存入上传时间
        LKSPUtil.getInstance().init(context);
        LKSPUtil.getInstance().putLongValue("uploadTime", System.currentTimeMillis());

        // 查询session数据、上传、删除
        List<LKSessionData> mSessionDataList = LKDbManager.getInstance().queryLKSessionData(context);
        //数据转换
        List<CollectorObj> list = dataListToCollectorRequestObj(mSessionDataList);
        // 上传session数据
        if (list != null && list.size() > 0) {
            Gson gson = new Gson();
            String collect = gson.toJson(list);
            // 调用主工程中的方法进行上传
            long time = mSessionDataList.get(0).timeId;
            LkCollectorHttp.init().upCollectInfo(LKConfig.UP_COLLECTOR_COLLECT, collect, context, time);
        }
    }

    /**
     * 参数转换
     *
     * @param dataList
     */
    private static List<CollectorObj> dataListToCollectorRequestObj(List<LKSessionData> dataList) {
        List<CollectorObj> datas = new ArrayList<>();
        CollectorObj collectorObj;
        for (LKSessionData data : dataList) {
            collectorObj = new CollectorObj();
            collectorObj.action = data.action;
            collectorObj.appKey = data.appKey;
            collectorObj.appVersion = data.appVersion;
            collectorObj.area_id = data.area_id;
            collectorObj.city_id = data.city_id;
            collectorObj.country_id = data.country_id;
            collectorObj.date = data.date;
            collectorObj.region_id = data.region_id;
            collectorObj.userInfo = data.userInfo;

            DeviceBean device = new DeviceBean();
            device.connection = data.connection;
            device.deviceId = data.deviceId;
            device.deviceName = data.deviceName;
            device.mobileOperator = data.mobileOperator;
            device.osName = data.osName;
            device.osVersion = data.osVersion;
            collectorObj.device = device;

            Map<String, Object> map = new HashMap<>();
            if (null != data.eventId && data.eventId.length() > 0) {
                map.put("eventId", data.eventId);
            }

            if (null != data.label && data.label.length() > 0) {
                map.put("label", data.label);
            }

            if (null != data.duration && data.duration.length() > 0) {
                map.put("duration", data.duration);
            }

            if (null != data.attributes && data.attributes.length() > 0) {
                Map<String, String> attributes = LKCollectJsonUtil.parseJsonToMap(data.attributes);
                map.put("attributes", attributes);
            }

            collectorObj.parameter = map;
            datas.add(collectorObj);
        }

        return datas;

    }

    /**
     * 获取当前的运营商
     *
     * @return 运营商名字
     */
    private static String getOperator(Context context) {

        String ProvidersName = "";
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            return "";
        }
        String IMSI = telephonyManager.getSubscriberId();
        if (IMSI != null) {
            if (IMSI.startsWith("46000") || IMSI.startsWith("46002") || IMSI.startsWith("46007")) {
                ProvidersName = "1";
            } else if (IMSI.startsWith("46001") || IMSI.startsWith("46006")) {
                ProvidersName = "2";
            } else if (IMSI.startsWith("46003")) {
                ProvidersName = "3";
            }
            return ProvidersName;
        } else {
            return "";
        }
    }

    /**
     * 获取网络链接方式
     */
    private static String getConnect(Context context) {
        if (context != null) {
            ConnectivityManager mConnectivityManager = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
            if (mNetworkInfo == null || !mNetworkInfo.isAvailable()) {
                return "0";
            }
        }

        if (LKNetUtils.isWifiEthernetConnect(context)) {
            return "1";
        } else {
            return "2";
        }
    }

    /**
     * 得到当前应用版本名称的方法
     *
     * @param context :上下文
     * @throws Exception
     */
    private static String getVersionName(Context context) {
        // 获取packagemanager的实例
        PackageManager packageManager = context.getPackageManager();
        // getPackageName()是你当前类的包名
        PackageInfo packInfo;
        try {
            packInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return "";
        }
        String version = packInfo.versionName;
        return version;
    }

}
